package org.jeecg.modules.system.controller;

import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysClient;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysAuthorizeService;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: TODO
 * @author: 周天翼
 * @date: 2020年07月23日 11:20
 */

@RestController
@RequestMapping("/oauth")
@Api(tags="OAuth密码模式")
@Slf4j
public class OAuthController {

    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ISysAuthorizeService sysAuthorizeService;

    @ApiOperation("获取令牌接口")
    @PostMapping(value = "/token")
    public Result<JSONObject> getToken(HttpServletRequest request) throws OAuthSystemException {
        Result<JSONObject> result = new Result<JSONObject>();
        try {
            // 构建Oauth请求
            OAuthTokenRequest oAuthTokenRequest = new OAuthTokenRequest(request);
            if (oAuthTokenRequest.getGrantType().equals(GrantType.PASSWORD.toString())) {
                result = passwordAuth(oAuthTokenRequest);
            }else{
                result.error500(OAuthError.TokenResponse.UNSUPPORTED_GRANT_TYPE);
                return result;
            }
            return result;
        } catch (OAuthProblemException oAuthProblemException) {
            oAuthProblemException.printStackTrace();
            result.error500(oAuthProblemException.getMessage());
            return result;
        }
    }

    @ApiOperation("检查令牌入口")
    @PostMapping("/check_token")
    public Result<?> checkToken(@RequestParam(name = "token", required = false) String token) {
        try {

            String userInfo = JwtUtil.getUsername(token);
            log.info(" ------ 通过令牌获取部分用户信息，当前用户： " + userInfo);


            // 根据用户名查询用户信息
//            SysUser sysUser = JSONObject.parseObject(userInfo, SysUser.class);
            SysUser sysUser = sysUserService.getUserByName(userInfo);
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("sysUserId", sysUser.getId());
            map.put("sysUserCode", sysUser.getUsername()); // 当前登录用户登录账号
            map.put("sysUserName", sysUser.getRealname()); // 当前登录用户真实名称
            map.put("sysOrgCode", sysUser.getOrgCode()); // 当前登录用户部门编号

            log.info(" ------ 通过令牌获取部分用户信息，已获取的用户信息： " + userInfo);

            return Result.ok(map);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error(500, "查询失败:" + e.getMessage());
        }
    }

    /*
    * 密码授权模式
    * */
    private Result<JSONObject> passwordAuth(OAuthTokenRequest oAuthTokenRequest){
        Result<JSONObject> objectResult = new Result<JSONObject>();
        String username = oAuthTokenRequest.getUsername();
        String password = oAuthTokenRequest.getPassword();
        String ClientId = oAuthTokenRequest.getClientId();
        String ClientSecret = oAuthTokenRequest.getClientSecret();

        //1. 校验提交的客户端
        SysClient sysClient = sysAuthorizeService.getClientByClientId(ClientId);
        if(sysClient == null){
            objectResult.error500(OAuthError.TokenResponse.INVALID_CLIENT);
            return objectResult;
        }
        if(!sysClient.getClientSecret().equals(ClientSecret)){
            objectResult.error500(OAuthError.TokenResponse.INVALID_CLIENT);
            return objectResult;
        }

        //2. 校验用户是否有效
        SysUser sysUser = sysUserService.getUserByName(username);
        objectResult = sysUserService.checkUserIsEffective(sysUser);
        if(!objectResult.isSuccess()) {
            return objectResult;
        }

        //3. 校验用户名或密码是否正确
        String userPassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
        String sysPassword = sysUser.getPassword();
        if (!sysPassword.equals(userPassword)) {
            objectResult.error500("用户名或密码错误");
            return objectResult;
        }

        //用户信息,生成Access Token并返回
//        String userJson = JSONObject.toJSONString(sysUser);
        String token = JwtUtil.sign(username,sysPassword);
        //设置token缓存有效时间
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token,token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
        JSONObject obj = new JSONObject();
        obj.put("access_token",token);
        obj.put("token_type","Bearer");
        obj.put("expires_in",JwtUtil.EXPIRE_TIME * 2 / 1000);
        obj.put("scope","all");
        objectResult.setResult(obj);
        objectResult.success("认证成功");
        //添加日志
        sysBaseAPI.addLog("用户名: " + sysUser.getUsername() + ",登录成功！", CommonConstant.LOG_TYPE_1, null);
        return objectResult;
    }

}
